#include "processor.h"


typedef struct{
	unsigned int logicalRegister;
	unsigned int localRegister;
}localRMTType;

int processor::preRenamer(unsigned int *indices, unsigned int traceWidth)
{

	localRMTType *localRMTInt, *localRMTFloat;

	localRMTInt = new localRMTType[traceWidth];
	localRMTFloat = new localRMTType[traceWidth];

	int numLocalRMTEntriesInt = 0, numLocalRMTEntriesFloat = 0;

	// First look at destination registers and see if they are local or global or both
	for ( int i = 0; i < traceWidth; i++)
	{
		unsigned int iIndex = indices[i];

		if (PAY.buf[iIndex].C_valid)
		{ // See if the future intructions have the same destination register. If yes, someone is killing it => Not Golbal
			PAY.buf[iIndex].C_hierarchy |= GLOBAL_REGISTER;
			for (int j = i+1; j < traceWidth; j++)
			{
				unsigned int jIndex = indices[j];
				if (PAY.buf[jIndex].C_valid && (PAY.buf[jIndex].C_int == PAY.buf[iIndex].C_int) && (PAY.buf[jIndex].C_log_reg == PAY.buf[iIndex].C_log_reg))
				{
					PAY.buf[iIndex].C_hierarchy &= ~GLOBAL_REGISTER;
					break;
				}

				else //Global
					PAY.buf[iIndex].C_hierarchy |= GLOBAL_REGISTER;

			}


			// Now, to avoid allocating local registers to the Global live-outs only
			unsigned int k, kIndex;
			for (k = i+1; k < traceWidth; k++)
			{
				kIndex = indices[k];

				if (PAY.buf[kIndex].A_valid &&
						(PAY.buf[kIndex].A_log_reg == PAY.buf[iIndex].C_log_reg) &&
						(PAY.buf[kIndex].A_int == PAY.buf[iIndex].C_int))
				{
					PAY.buf[iIndex].C_hierarchy |= LOCAL_REGISTER;
					break;
				}

				if (PAY.buf[kIndex].B_valid &&
						(PAY.buf[kIndex].B_log_reg == PAY.buf[iIndex].C_log_reg) &&
						(PAY.buf[kIndex].B_int == PAY.buf[iIndex].C_int))
				{
					PAY.buf[iIndex].C_hierarchy |= LOCAL_REGISTER;
					break;
				}

				PAY.buf[iIndex].C_hierarchy &= ~LOCAL_REGISTER;
			}

		} //End dst valid
	}//End for loop



	for ( int i = 0; i < traceWidth; i++)
	{
		unsigned int iIndex = indices[i];

		//Rename the sources first. Assume source is a Global Live in
		PAY.buf[iIndex].A_hierarchy = GLOBAL_REGISTER;
		PAY.buf[iIndex].B_hierarchy = GLOBAL_REGISTER;

		//Maintain a local RMT and search through it for each source
		int j; // = numLocalRMTEntriesInt -1;
		int k; // = numLocalRMTEntriesFloat -1;

		//Local RMT contains all the mappings that are renamed to locals. One entry per one local register
		if (PAY.buf[iIndex].A_valid)
		{
			if (PAY.buf[iIndex].A_int)//integer source
			{
				for (j = numLocalRMTEntriesInt -1; j>=0 ; j--)
				{
					if(localRMTInt[j].logicalRegister == PAY.buf[iIndex].A_log_reg)
					{
						PAY.buf[iIndex].A_loc_reg = localRMTInt[j].localRegister;
						PAY.buf[iIndex].A_hierarchy = LOCAL_REGISTER;

						break;
					}
				}
			}
			else //fp
			{
				for (k = numLocalRMTEntriesFloat -1; k>=0 ; k--)
				{
					if(localRMTFloat[k].logicalRegister == PAY.buf[iIndex].A_log_reg)
					{
						PAY.buf[iIndex].A_loc_reg = localRMTFloat[k].localRegister;
						PAY.buf[iIndex].A_hierarchy = LOCAL_REGISTER;

						break;
					}
				}
			}
		}


		if (PAY.buf[iIndex].B_valid)
		{
			if(PAY.buf[iIndex].B_int)
			{
				for (j = numLocalRMTEntriesInt -1; j>=0 ; j--)
				{
					if(localRMTInt[j].logicalRegister == PAY.buf[iIndex].B_log_reg)
					{
						PAY.buf[iIndex].B_loc_reg = localRMTInt[j].localRegister;
						PAY.buf[iIndex].B_hierarchy = LOCAL_REGISTER;

						break;
					}
				}
			}
			else
			{
				for (k = numLocalRMTEntriesFloat -1; k>=0 ; k--)
				{
					if(localRMTFloat[k].logicalRegister == PAY.buf[iIndex].B_log_reg)
					{
						PAY.buf[iIndex].B_loc_reg = localRMTFloat[k].localRegister;
						PAY.buf[iIndex].B_hierarchy = LOCAL_REGISTER;

						break;
					}
				}
			}
		}




		//Destination now:
		//Look at each destinations status register and decide

		if (PAY.buf[iIndex].C_valid && PAY.buf[iIndex].C_int)
		{
			if (PAY.buf[iIndex].C_hierarchy & LOCAL_REGISTER)
			{
				PAY.buf[iIndex].C_loc_reg = numLocalRMTEntriesInt;
				localRMTInt[numLocalRMTEntriesInt].localRegister = numLocalRMTEntriesInt;
				localRMTInt[numLocalRMTEntriesInt].logicalRegister = PAY.buf[iIndex].C_log_reg;
				numLocalRMTEntriesInt ++;
			}
		}

		if (PAY.buf[iIndex].C_valid && !PAY.buf[iIndex].C_int)
		{
			if (PAY.buf[iIndex].C_hierarchy & LOCAL_REGISTER)
			{
				PAY.buf[iIndex].C_loc_reg = numLocalRMTEntriesFloat;
				localRMTInt[numLocalRMTEntriesFloat].localRegister = numLocalRMTEntriesFloat;
				localRMTInt[numLocalRMTEntriesFloat].logicalRegister = PAY.buf[iIndex].C_log_reg;
				numLocalRMTEntriesFloat ++;
			}
		}


	}



	return numLocalRMTEntriesInt + numLocalRMTEntriesFloat;
}

